﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using Quiz.LINQData;

namespace Quiz
{
    class AktuellesQuiz : DependencyObject
    {
        #region DepencyProperties
            //Depency Properties für die Oberfläche, da hier Livedaten abgefragt werden.
            public static readonly DependencyProperty RestZeitProperty = DependencyProperty.Register("RestZeit", typeof(int), typeof(AktuellesQuiz));
            public static readonly DependencyProperty StatusProperty = DependencyProperty.Register("Status", typeof(QuizStatus), typeof(AktuellesQuiz));
            public static readonly DependencyProperty FalscheAntwortenProperty = DependencyProperty.Register("FalscheAntworten", typeof(int), typeof(AktuellesQuiz));
            public static readonly DependencyProperty RichtigeAntwortenProperty = DependencyProperty.Register("RichtigeAntworten", typeof(int), typeof(AktuellesQuiz));
            public static readonly DependencyProperty UebersprungeneAntwortenProperty = DependencyProperty.Register("UebersprungeneAntworten", typeof(int), typeof(AktuellesQuiz));
            public static readonly DependencyProperty AktuelleFrageProperty = DependencyProperty.Register("AktuelleFrage", typeof(Frage), typeof(AktuellesQuiz));
            public static readonly DependencyProperty AntwortStatusProperty = DependencyProperty.Register("AntwortStatus", typeof(Antwort.AntwortStatus), typeof(AktuellesQuiz));
            public static readonly DependencyProperty AktuellesBildProperty = DependencyProperty.Register("AktuellesBild", typeof(ImageSource), typeof(AktuellesQuiz));
            private static readonly DependencyProperty OptionAuswahlProperty = DependencyProperty.Register("OptionenAuswahl", typeof(OptionenAuswahl), typeof(DataBase));
        #endregion

        #region Member
            private Spielklasse _spielklasse;
            DispatcherTimer _gameTimer;

            public enum QuizStatus
            {
                Auswertung,
                Laeuft,
                Nichtgestartet,
                Beendet
            }
        #endregion

        
        #region Properties
            /// <summary>
            /// Die Anzahl der falschen Antworten die bisher gegeben wurden.
            /// </summary>
            public int FalscheAntworten
            {
                get { return (int)GetValue(FalscheAntwortenProperty); }
                set { SetValue(FalscheAntwortenProperty, value); }
            }
            
            /// <summary>
            /// Die Anzahl der richtigen Antworten die bisher gegeben wurden
            /// </summary>
            public int RichtigeAntworten
            {
                get { return (int)GetValue(RichtigeAntwortenProperty); }
                set {  SetValue(RichtigeAntwortenProperty, value); }
            }
            
            /// <summary>
            /// Die Restzeit die noch für das Quiz bleibt, greift auf das DepencyProperty zurück
            /// </summary>
            public int RestZeit
            {
                get { return (int)GetValue(RestZeitProperty); }
                set { SetValue(RestZeitProperty,value); }
            }

            /// <summary>
            /// Gibt die übersprungenen Antworten aus dem Quiz zurück
            /// </summary>
            public int UebersprungeneAntworten
            {
                get { return (int)GetValue(UebersprungeneAntwortenProperty) ; }
                set { SetValue(UebersprungeneAntwortenProperty, value); }
            }

            /// <summary>
            /// Die Aktuelle Frage des aktuellen Quizes
            /// </summary>
            public Frage AktuelleFrage
            {
                get { return (Frage)GetValue(AktuelleFrageProperty); }
                set { SetValue(AktuelleFrageProperty, value); }
            }

            /// <summary>
            /// Gibt zurück ob ein aktuelles Spielt läuft
            /// </summary>
            public QuizStatus Status
            {
                get { return (QuizStatus)GetValue(StatusProperty); }
                set { SetValue(StatusProperty, value); }
            }

            /// <summary>
            /// Gibt den aktuellen Antwortstatus zurück
            /// </summary>
            public Antwort.AntwortStatus AntwortStatus
            {
                get { return (Antwort.AntwortStatus)GetValue(AntwortStatusProperty); }
                set { SetValue(AntwortStatusProperty, value); }
            }

            /// <summary>
            /// Gibt das aktuelle Bild zurück was angezeigt werden soll, wärend eines Tests.
            /// </summary>
            public ImageSource AktuellesBild
            {
                get { return (ImageSource)GetValue(AktuellesBildProperty); }
                set { SetValue(AktuellesBildProperty, value); }
            }

            /// <summary>
            /// Direkter Zugriff auf die Wichtigsten Optionen die in der Datenbank hinterlegt wurden in der OptionenTabelle, bereits fertig aufbereitet.
            /// </summary>
            public OptionenAuswahl OptionAuswahl
            {
                get { return (OptionenAuswahl)GetValue(OptionAuswahlProperty); }
                set { SetValue(OptionAuswahlProperty, value); }
            }

        #endregion


        #region Konstruktor
            /// <summary>
            /// Initialisieren des Aktuellen Quizes
            /// </summary>
            public AktuellesQuiz()
            {
                _spielklasse = new Spielklasse();
                Status = QuizStatus.Nichtgestartet;
                FalscheAntworten = 0;
                RichtigeAntworten = 0;
                UebersprungeneAntworten = 0;
                AktuellesBild = (ImageSource)Application.Current.FindResource("Startbild");

                //Initialisieren des Timers der die Spielzeit herunterzählt
                _gameTimer = new DispatcherTimer();
                _gameTimer.Tick += new EventHandler(dispatcherTimer_RestZeitQuiz);
                _gameTimer.Interval = new TimeSpan(0, 0, 1);

                //Laden aller wichtigen Optionen für die Schriftgroessen
                OptionAuswahl = new OptionenAuswahl(_spielklasse.Datenbank.Optionen);
            }
        #endregion


        #region Functions/Subs
            /// <summary>
            /// Startet ein neues Quiz und setzt alle wichtigen Variablen zurück
            /// </summary>
            public void QuizStarten()
            {
                Status = QuizStatus.Laeuft;
                FalscheAntworten = 0;
                RichtigeAntworten = 0;
                UebersprungeneAntworten = 0;
                RestZeit = OptionAuswahl.TestzeitInSekunden;

                //DispatcherTimer erstellen, für die Zeit nach dem eine Frage beantwortet wurde.
                _gameTimer.Start();
            }

            /// <summary>
            /// Beendet ein Quit
            /// </summary>
            public void QuizBeenden()
            {
                RestZeit = 0;
                Status = AktuellesQuiz.QuizStatus.Beendet;
                AktuellesBild = (ImageSource)Application.Current.FindResource("TestBeendet");
            }

            /// <summary>
            /// Setzt die nächste Frage im Quiz
            /// </summary>
            /// <param name="uxAntwortenP"></param>
            public void NaechsteFrage(ItemsControl uxAntwortenP)
            {
                //Den Aktuellen Quizstatus auf Laueft setzten
                Status = AktuellesQuiz.QuizStatus.Laeuft;
                AntwortStatus = Antwort.AntwortStatus.NeueFrage;
                
                SetzteAktuellesFrageBild();
                //Herraussuchen einer neuen "Randomfrage" aus allen gewünschten Fragen
                AktuelleFrage = _spielklasse.GetNewRandomFrage();

                if (AktuelleFrage != null)
                {
                    //dafür sorgen, das die Antworten immer unterschiedlich "Nummeriert" sind.
                    AktuelleFrage.AddRandomAntwortNummerierung();

                    //Query anfertigen, was die antworten nach den AntwortPos sortiert und dann das Query der ItemsSource zur Anzeige übergebem
                    var query = from antwort in AktuelleFrage.Antworten orderby antwort.AntwortPos select antwort;
                    uxAntwortenP.ItemsSource = query;
                }
            }
            

            /// <summary>
            /// Überprüft ob die gegebene Antwort die richtige war und löscht außerderm aus der aktuellen Antwortliste alle falschen Antworten heraus.
            /// </summary>
            /// <param name="antwortID">Die ID die als "Richtig" angeben wurde.</param>
            /// <returns>TRUE-> Antwort war richtig | FALSE-> Antwort war falsch</returns>
            public Antwort.AntwortStatus FrageAntwortAuswertung(int antwortID)
            {
                //Den Status des Quiz auf Auswertung setzten
                Status = AktuellesQuiz.QuizStatus.Auswertung;

                //Jede Antwort durchgehen und prüfen ob es sich um die Antwort handelt die der Spielder ausgewählt hat.
                foreach (Antwort antwort in AktuelleFrage.Antworten)
                {
                    //Wenn die ID gefunden wurde die ausgwählt wurde, dann das ERgebnis speichern ob dies richtig war oder nicht.
                    if (antwort.AntwortPos == antwortID)
                    {
                        //Wenn die AntwortID Int.MinValue ist, dann handelt es sich um eine übersprungene Frage.
                        if (antwort.AntwortID == int.MinValue)
                        {
                            AntwortStatus = Antwort.AntwortStatus.UeberSprungen;
                            AddUebersprungeneAntwort();
                        }
                        else
                        {
                            //Prüfen welchen Status die Antwort selbst hat und diesen speichern.
                            if (antwort.Richtig)
                            {
                                AntwortStatus = Antwort.AntwortStatus.Richtig;
                                AddRichtigeAntwort();
                            }
                            else
                            {
                                AntwortStatus = Antwort.AntwortStatus.Falsch;
                                AddFalscheAntwort();
                            }
                        }
                        break;
                    }
                }

                //Setzten des aktuellen "Fragebildes"
                SetzteAktuellesFrageBild();
                //Gibt den aktuellen Antwortstatus zurück
                return AntwortStatus;
            }

            /// <summary>
            /// Bestimmt im Fragemodus welches bild gerade angezeigt werden soll.
            /// </summary>
            private void SetzteAktuellesFrageBild()
            {
                switch (AntwortStatus)
                {
                    case Antwort.AntwortStatus.Falsch:
                        //Die ImageSource aus den Resourcen laden mittels des hinterlegten Keys in den Ressourcen
                        AktuellesBild = (ImageSource)Application.Current.FindResource("Falsch");
                        break;
                    case Antwort.AntwortStatus.Richtig:
                        AktuellesBild = (ImageSource)Application.Current.FindResource("Richtig");
                        break;
                    case Antwort.AntwortStatus.UeberSprungen:
                        AktuellesBild = (ImageSource)Application.Current.FindResource("Uebersprungen");
                        break;
                    case Antwort.AntwortStatus.NeueFrage:
                        AktuellesBild = (ImageSource)Application.Current.FindResource("Frage");
                        break;
                }
            }

            /// <summary>
            /// Gibt die Anzahl der Gesamtantworten für das aktuelle Quiz zurück
            /// </summary>
            public int GesamtAntworten()
            {
                return FalscheAntworten + RichtigeAntworten;
            }
            
            /// <summary>
            /// Addiert eine Richtige Antwort hinzu
            /// </summary>
            public void AddRichtigeAntwort()
            {
                RichtigeAntworten++;
            }

            /// <summary>
            /// Addiert eine falsche Antwort hinzu
            /// </summary>
            public void AddFalscheAntwort()
            {
                FalscheAntworten++;
            }
            
            /// <summary>
            /// Addiert eine übersprungene Antwort hinzu
            /// </summary>
            public void AddUebersprungeneAntwort()
            {
                UebersprungeneAntworten++;
            }
        #endregion


        #region Events
            private void dispatcherTimer_RestZeitQuiz(object sender, EventArgs e)
            {
                //Jedesmal wenn der Timer aufgerufen wird, wird die Restzeit um 1 subtrahiert.
                RestZeit--;

                if (RestZeit <= 0)
                {
                    RestZeit = 0;
                    _gameTimer.Stop();
                    //Das Quiz beenden, wenn die Zeit abgelaufen ist.
                    QuizBeenden();
                }
            }

        #endregion
    }
}
